//
//  File.swift
//  SyncKit
//
//  Created by tangjilin on 2025/7/15.
//



import Foundation
import WatchConnectivity

public final class WatchFileSync:NSObject {
    // 单例模式
    @MainActor public static let shared = WatchFileSync()
    
    // 文件过滤器类型
    public typealias FileFilter = (URL) -> Bool
    
    // 同步完成回调
    public typealias SyncCompletion = (Result<[String], Error>) -> Void
    
    // 存储文件传输的 completion 回调
    private var fileCompletionHandlers: [String: (Result<Void, Error>) -> Void] = [:]
    
    // 私有初始化器
    private override init() {
        super.init()
        setupSession()
    }
    
    // 设置 Watch Connectivity 会话
    private func setupSession() {
        if WCSession.isSupported() {
            let session = WCSession.default
            session.delegate = self
            session.activate()
            print("Watch Connectivity 会话已激活")
        } else {
            print("Watch Connectivity 不支持")
        }
    }
    
    // 同步所有符合条件的文件到 iPhone
    public func syncAllDocumentsToPhone(filter: FileFilter? = nil, completion: SyncCompletion? = nil) {
        guard WCSession.default.activationState == .activated else {
            completion?(.failure(SyncError.sessionNotActivated))
            return
        }
        
        let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
        
        do {
            let fileURLs = try FileManager.default.contentsOfDirectory(at: documentsURL, includingPropertiesForKeys: nil)
            
            // 应用自定义过滤器（如果有）
            let filteredURLs = fileURLs.filter { filter?($0) ?? true }
            
            // 应用默认的 .caf 扩展名过滤
            let filesToSync = filteredURLs.filter { $0.pathExtension.lowercased() == "caf" }
            
            if filesToSync.isEmpty {
                completion?(.success([]))
                return
            }
            
            print("找到 \(filesToSync.count) 个文件需要同步")
            
            var syncedFiles: [String] = []
            var failedFiles: [String: Error] = [:]
            
            // 使用 DispatchGroup 跟踪所有文件的同步状态
            let group = DispatchGroup()
            
            for fileURL in filesToSync {
                group.enter()
                
                syncFile(fileURL) { result in
                    defer { group.leave() }
                    
                    switch result {
                    case .success:
                        syncedFiles.append(fileURL.lastPathComponent)
                    case .failure(let error):
                        failedFiles[fileURL.lastPathComponent] = error
                    }
                }
            }
            
            group.notify(queue: .main) {
                if !failedFiles.isEmpty {
                    let error = SyncError.partialSyncFailed(synced: syncedFiles, failed: failedFiles)
                    completion?(.failure(error))
                } else {
                    completion?(.success(syncedFiles))
                }
            }
            
        } catch {
            completion?(.failure(SyncError.failedToRetrieveFiles(error)))
        }
    }
    // 同步单个文件
    private func syncFile(_ fileURL: URL, completion: ((Result<Void, Error>) -> Void)? = nil) {
        guard WCSession.default.isReachable else {
            completion?(.failure(SyncError.phoneNotReachable))
            return
        }
        
        // 显式指定字典类型为 [String : Any]
        let metadata: [String : Any] = [
            "fileName": fileURL.lastPathComponent,
            "date": Date().timeIntervalSince1970
        ]
        
        let transfer = WCSession.default.transferFile(fileURL, metadata: metadata)
        
        // 保存 completion 回调，用于后续处理
        let fileName = fileURL.lastPathComponent
        if let completion = completion {
            fileCompletionHandlers[fileName] = completion
        }
    }
}

// MARK: - 错误类型
public enum SyncError: Error {
    case sessionNotActivated
    case phoneNotReachable
    case failedToRetrieveFiles(Error)
    case fileNotFound(String)
    case transferFailed(String, Error)
    case partialSyncFailed(synced: [String], failed: [String: Error])
}

// MARK: - WCSessionDelegate
extension WatchFileSync: WCSessionDelegate {
  
    
    public func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
        print("会话激活完成: \(activationState)")
        if let error = error {
            print("会话激活错误: \(error)")
        }
    }
    
    public func sessionReachabilityDidChange(_ session: WCSession) {
        print("iPhone 可达性变化: \(session.isReachable)")
    }
    
    public func session(_ session: WCSession, didReceive file: WCSessionFile) {
        let fileName = file.metadata?["fileName"] as? String ?? "unknown"
        print("收到文件: \(fileName)")
        
        // 将文件保存到Documents目录
        do {
            let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
            let destinationURL = documentsURL.appendingPathComponent(fileName)
            
            // 如果文件已存在，先删除
            if FileManager.default.fileExists(atPath: destinationURL.path) {
                try FileManager.default.removeItem(at: destinationURL)
            }
            
            // 移动文件到目标位置
            try FileManager.default.moveItem(at: file.fileURL, to: destinationURL)
            print("文件已保存到: \(destinationURL)")
            
            // 调用对应的completion回调
            if let completion = fileCompletionHandlers[fileName] {
                completion(.success(()))
                fileCompletionHandlers.removeValue(forKey: fileName)
            }
        } catch {
            print("保存文件失败: \(error)")
            if let completion = fileCompletionHandlers[fileName] {
                completion(.failure(SyncError.transferFailed(fileName, error)))
                fileCompletionHandlers.removeValue(forKey: fileName)
            }
        }
    }
    
    // 可选实现：根据需要添加
    public func sessionDidBecomeInactive(_ session: WCSession) {
        // 可以添加会话变为非活动状态时的处理逻辑
    }
    
    public func sessionDidDeactivate(_ session: WCSession) {
        // 可以添加会话被停用时的处理逻辑，例如重新激活会话
        session.activate()
    }
}
